/**
 * 
 */
package cc.dogtailflower.framework;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cc.dogtailflower.framework.bean.Data;
import cc.dogtailflower.framework.bean.Param;
import cc.dogtailflower.framework.bean.RequestBean;
import cc.dogtailflower.framework.bean.View;
import cc.dogtailflower.framework.constant.RequestMethod;
import cc.dogtailflower.framework.handler.BeanHandler;
import cc.dogtailflower.framework.handler.ConfigHandler;
import cc.dogtailflower.framework.handler.ControllerHandler;
import cc.dogtailflower.framework.handler.RequestHandler;
import cc.dogtailflower.framework.handler.ServletHandler;
import cc.dogtailflower.framework.util.JsonUtil;
import cc.dogtailflower.framework.util.ReflectionUtil;
import cc.dogtailflower.framework.util.StringUtil;

/**
 * mvc中最重要的一个类，请求转发器！
 * @author cc
 *
 */
@WebServlet(urlPatterns = "/*",loadOnStartup = 0) //初始化时候第一个加载
public class DispatcherServlet extends HttpServlet{

	/**
	 * 
	 */
	private static final long serialVersionUID = 4606425828605725887L;
	
	/*
	 * 类初始化时候只会执行一次
	 */
	@Override
	public void init(ServletConfig servletConfig)throws ServletException{
		
		//初始化HelplerLoader
		HelperLoader.allocAndInit();
		//注册JSP 并 配置映射路径
		ServletContext servletContext = servletConfig.getServletContext();
		ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
		jspServlet.addMapping(ConfigHandler.getViewPath()+"*");
		
		//注册静态资源默认的Servlet
		ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
		defaultServlet.addMapping(ConfigHandler.getAssetPath()+"*");
		
	}
	
	public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
		ServletHandler.init(request, response);
		try{
			String requestMethod = request.getMethod().toUpperCase();
			RequestMethod requestMethodEnum = null;
			for(RequestMethod rm : RequestMethod.values()){
				if(rm.toString().equals(requestMethod)){
					requestMethodEnum = rm;
				}
			}
			String requestPath = request.getPathInfo();
			
			if(requestPath.equals("/favicon.ico")){
				return;
			}
			
			//获取 RequestMapping 处理器
			RequestBean requestBean = ControllerHandler.getRquestHandler(requestPath, requestMethodEnum);
			if(requestBean != null){
				//获取Controller类及其实例对象
				Class<?> controllerClass = requestBean.getControllerClass();
				Object controllerBean = BeanHandler.getBeanFromMap(controllerClass);
				Param param = RequestHandler.createParam(request);
				
				Object result;
				
				Method requestMappingMethod = requestBean.getRequestMappingMethod();
				//反射调用类中的具体方法，分为是否有参数
				if(param.isEmpty()){
					result = ReflectionUtil.invokerMethod(controllerBean, requestMappingMethod);
				}else{
					result = ReflectionUtil.invokerMethod(controllerBean, requestMappingMethod,param);
				}
				
				//判断结果什么类型，是返回值，返回页面
				if(result instanceof View){
					handleViewResult((View)result,request,response);
				}else if(result instanceof Data){
					handleDataResult((Data)result,response);
				}
			}
		}finally{
			ServletHandler.destroy();
		}
	}
	
	private void handleViewResult(View view,HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException{
		String viewPath = view.getViewPath();
		if(StringUtil.isNotEmpty(viewPath)){
			Map<String,Object> model = view.getModel();
			for(Map.Entry<String, Object> entry : model.entrySet()){
				request.setAttribute(entry.getKey(), entry.getValue());
			}
			//转发到目标路径，为路径加上前缀
			request.getRequestDispatcher(ConfigHandler.getViewPath()+viewPath).forward(request, response);
		}
	}
	
	private void handleDataResult(Data data,HttpServletResponse response) throws IOException,ServletException{
		Object model = data.getModel();
		if(model != null){
			response.setContentType("application/json");
			response.setCharacterEncoding("UTF-8");
			PrintWriter pw = response.getWriter();
			String json = JsonUtil.toJson(model);
			pw.write(json);
			pw.flush();
			pw.close();
		}
	}

}
